package web

import (
	"encoding/json"
	"fmt"
	beego "github.com/beego/beego/v2/server/web"
	"ksd-social-api/commons/base/controller"
	"ksd-social-api/modules/common/sms/contants"
	"ksd-social-api/modules/login/model/context"
	"ksd-social-api/modules/login/model/dto"
	"ksd-social-api/modules/login/model/vo"
	context3 "ksd-social-api/modules/msg/model/context"
	"ksd-social-api/utils"
	"ksd-social-api/utils/rdb"
	"net/http"
	"strconv"
	"strings"
)

type WeixinLoginController struct {
	controller.BaseController
}

//state生成器
//redis

/**
 * 微信登录
 * @author feige
 * @date 2024-01-17
 * @version 1.0
 * @desc
 */
// 微信扫码登录成功以后的回调地址
func (web *WeixinLoginController) WexinLogin() {
	// code ---> openid
	// 获取微信用户扫一扫以后登录的code信息00000
	code := web.GetString("code")
	// 获取到验证的state信息
	state := web.GetString("state")
	// 获取到验证的state信息
	systemIds := web.GetString("systemid")
	split := strings.Split(systemIds, "_")
	systemId, _ := strconv.ParseUint(split[0], 10, 64)
	userId, _ := strconv.ParseUint(split[1], 10, 64)
	appid := beego.AppConfig.DefaultString("weixin.login.appid", "")
	secret := beego.AppConfig.DefaultString("weixin.login.secret", "")
	// 通过code获取到openid的过程。
	url := "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code"
	targetUrl := fmt.Sprintf(url, appid, secret, code)
	// 发起的登录请求获取openid
	resp, err := http.Get(targetUrl)
	// 关闭链接
	defer resp.Body.Close()

	// 如果请求没有异常
	if err == nil {
		wxLoginResp := context.WXLoginResp{}
		wxLoginResp.SystemId = systemId
		wxLoginResp.SystemName = "学习512"
		decoder := json.NewDecoder(resp.Body)
		err := decoder.Decode(&wxLoginResp)
		if err == nil {
			// 获取到验证的state信息
			if userId > 0 { // 如果是登录状态的话，就直接绑定微信登录
				user := userService.GetUserInfoByOpenId(wxLoginResp.OpenId, wxLoginResp.SystemId)
				if user == nil {
					userService.UpdateUserOpenId(userId, systemId, wxLoginResp.OpenId)
					web.Ok("success")
				} else {
					web.Ok("微信绑定失败，已被占用，暂时不支持账号合并功能！")
				}
			} else {
				cacheKey := fmt.Sprintf("%s:%d:%s:%s", contants.WEIXIN_LOGIN_KEY, wxLoginResp.SystemId, state, web.GetIpAddr())
				cacheCode, _ := rdb.RdbGet(cacheKey)
				if len(cacheCode) > 0 {
					web.TplName = "login.html"
					web.Render()
					return
				}
				// 判断当前的openid是不是已经注册了
				user := userService.GetUserInfoByOpenId(wxLoginResp.OpenId, wxLoginResp.SystemId)
				if user == nil {
					// 开始注册
					userModel, _ := loginService.RegByWeixin(&wxLoginResp)
					go func() {
						// 保存默认消息---rabbitmq---生成这 --- 消费者
						messagePointService.SaveMessagePonitDefault(userModel.Id, systemId, userModel.Uuid)
						// 注册消息发送---rabbitmq 100ms
						messageMeContext := context3.MessageMeContext{}
						messageMeContext.UserId = userModel.Id
						messageMeContext.Uuid = userModel.Uuid
						messageMeContext.SystemId = systemId
						messageMeContext.SystemName = "系统512"
						messageMeContext.Username = userModel.Nickname
						messageMeService.SaveMessageMeReg(&messageMeContext)
					}()

					// 更新openid
					rdb.RdbSetEX(cacheKey, userModel.Uuid, contants.WEIXIN_LOGIN_LIMIT_SECONDS)
					// 为什么返回页面，如果返回json,在前端有格式，就很丑
					web.TplName = "login.html"
					web.Render()
				} else {
					if user.Forbidden == 1 {
						web.FailCodeMsg(701, "你被管理员关进了小黑屋！！")
						return
					}
					rdb.RdbSetEX(cacheKey, user.Uuid, contants.WEIXIN_LOGIN_LIMIT_SECONDS)
					web.TplName = "login.html"
					web.Render()
				}
			}

		}
	}
}

/**
 * 微信登录回调 1706018042899 1706018042899
 * @author feige
 * @date 2024-01-21
 * @version 1.0
 * @desc
 */
func (web WeixinLoginController) WexinLoginCallback() {
	// 获取到验证的state信息
	state := web.GetString("state")
	// 获取到验证的state信息
	systemId, _ := web.GetUint64("systemid")
	// 如果是登录的情况下，就是绑定微信
	userId, _ := web.GetUint64("userId")
	if userId > 0 {
		userVo := userService.GetUserInfo(userId, systemId)
		if len(userVo.OpenId) == 0 {
			web.FailCodeMsg(602, "fail")
			return
		} else {
			// 4: 开始把登录的用户信息，生成token进行返回
			loginVo := vo.LoginVo{}
			loginVo.VipDays = userVo.VipDays
			loginVo.RegDays = userVo.RegDays
			loginVo.Uuid = userVo.Uuid
			loginVo.Username = userVo.Username
			loginVo.Avatar = userVo.Avatar
			loginVo.Telephone = userVo.Telephone
			loginVo.Address = userVo.Address
			loginVo.Nickname = userVo.Nickname
			loginVo.Role = userVo.Role
			loginVo.Viptype = userVo.VipFlag
			loginVo.AuthorFlag = userVo.AuthorFlag
			loginVo.TeacherFlag = userVo.TeacherFlag
			// 把登录的用户信息写入到缓存中 --map
			cacheKey := fmt.Sprintf("LOGIN:USER:%s", loginVo.Uuid)
			// 这里把用用户需要的信息，放入缓存中
			userDto := dto.UserDto{}
			utils.CopyProperties(&userDto, userVo)
			// 开始把用户信息写入到缓存中
			rdb.RdbHSet(cacheKey, "user", utils.StructToJson(userDto))

			web.Ok(loginVo)
		}
	} else {
		// 扫码登录
		loginCacheKey := fmt.Sprintf("%s:%d:%s:%s", contants.WEIXIN_LOGIN_KEY, systemId, state, web.GetIpAddr())
		uuidCache, _ := rdb.RdbGet(loginCacheKey)
		if len(uuidCache) == 0 {
			web.FailCodeMsg(602, "fail")
			return
		}
		saveUser := userService.GetUserInfoByUuid(uuidCache, systemId)
		if saveUser != nil {
			if saveUser.Forbidden == 1 {
				web.FailCodeMsg(701, "你被管理员关进了小黑屋！！")
				return
			}
			// 4: 开始把登录的用户信息，生成token进行返回
			loginVo := vo.LoginVo{}
			loginVo.VipDays = saveUser.VipDays
			loginVo.RegDays = saveUser.RegDays
			loginVo.Uuid = saveUser.Uuid
			loginVo.Username = saveUser.Username
			loginVo.Avatar = saveUser.Avatar
			loginVo.Telephone = saveUser.Telephone
			loginVo.Address = saveUser.Address
			loginVo.Nickname = saveUser.Nickname
			loginVo.Role = saveUser.Role
			loginVo.Viptype = saveUser.VipFlag
			loginVo.AuthorFlag = saveUser.AuthorFlag
			loginVo.TeacherFlag = saveUser.TeacherFlag
			// 把登录的用户信息写入到缓存中 --map
			cacheKey := fmt.Sprintf("LOGIN:USER:%s", loginVo.Uuid)
			// 这里把用用户需要的信息，放入缓存中
			userDto := dto.UserDto{}
			utils.CopyProperties(&userDto, saveUser)
			// 开始把用户信息写入到缓存中
			rdb.RdbHSet(cacheKey, "user", utils.StructToJson(userDto))

			rdb.RdbDel(loginCacheKey)
			web.Ok(loginVo)
		}
	}
}
